﻿using System;
using System.Collections.Generic;
using System.Text;
using Pixysoft.Framework.Security.Core;
using Pixysoft.Framework.Configurations;
using Pixysoft.Net.Crawler;

namespace Pixysoft.Framework.Security
{
    class SSoConnection : ISSoConnection
    {
        private const int default_timeout_tokenconnection = 5000; // 5 sec

        string url;

        public SSoConnection(string url)
        {
            this.url = url;
        }

        public ISSoTokenLoginResponse TokenLogin(string username, string md5password, int timeoutMins)
        {
            if (string.IsNullOrEmpty(username)) throw new Exception("missing username");
            if (string.IsNullOrEmpty(md5password)) throw new Exception("missing md5password");

            LoggerHelper.Info("begin token login, username = {0}", username);

            SSoLoginRequest entityrequest = new SSoLoginRequest();
            entityrequest.UserName = username;
            entityrequest.Md5password = md5password;
            entityrequest.TimeoutMins = timeoutMins;
            string content = XmlManager.Serialize(entityrequest).Serialize();
            string compresscontent = Pixysoft.IO.Compressor.Instance.Compress(content);
            string encryptcontent = Pixysoft.Security.DES.Encrypt(compresscontent, StringHelper.global_framework_id);
            string base64content = Pixysoft.Security.Base64.Encript(encryptcontent);
            IXmlNode request = SSoCommandController.Instance.CreateRequest(null, SSoCommandCollection.TokenLogin, base64content);

            IXmlNode response = GetResponse(url, request.Serialize(), default_timeout_tokenconnection);
            if (response == null)
                return null;
            try
            {
                base64content = response.Text;
                encryptcontent = Pixysoft.Security.Base64.Decript(base64content);
                compresscontent = Pixysoft.Security.DES.Decrypt(encryptcontent, StringHelper.global_framework_id);
                content = Pixysoft.IO.Compressor.Instance.DeCompress(compresscontent);
                return Pixysoft.IO.XmlImporter.Instance.XmlDeserialize<SSoTokenLoginResponse>(content);
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(response.Text);
                throw new Exception(response.Text);
            }
        }

        public ISSoTokenLoginResponse TokenValidate(string token)
        {
            if (string.IsNullOrEmpty(token)) return null;

            LoggerHelper.Info("begin token validate, token = {0}", token);

            IXmlNode request = SSoCommandController.Instance.CreateRequest(token, SSoCommandCollection.TokenValidate, null);
            IXmlNode response = GetResponse(url, request.Serialize(), default_timeout_tokenconnection);
            try
            {
                string base64content = response.Text;
                string encryptcontent = Pixysoft.Security.Base64.Decript(base64content);
                string compresscontent = Pixysoft.Security.DES.Decrypt(encryptcontent, StringHelper.global_framework_id);
                string content = Pixysoft.IO.Compressor.Instance.DeCompress(compresscontent);
                return Pixysoft.IO.XmlImporter.Instance.XmlDeserialize<SSoTokenLoginResponse>(content);
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(response.Text);
                throw new Exception(response.Text);
            }
        }

        public ISSoTokenLoginResponse TokenExtend(string token)
        {
            if (string.IsNullOrEmpty(token)) return null;

            LoggerHelper.Info("begin token extend, token = {0}", token);

            IXmlNode request = SSoCommandController.Instance.CreateRequest(token, SSoCommandCollection.TokenExtend, null);
            IXmlNode response = GetResponse(url, request.Serialize(), default_timeout_tokenconnection);
            try
            {
                string base64content = response.Text;
                string encryptcontent = Pixysoft.Security.Base64.Decript(base64content);
                string compresscontent = Pixysoft.Security.DES.Decrypt(encryptcontent, StringHelper.global_framework_id);
                string content = Pixysoft.IO.Compressor.Instance.DeCompress(compresscontent);
                return Pixysoft.IO.XmlImporter.Instance.XmlDeserialize<SSoTokenLoginResponse>(content);
            }
            catch (Exception ex)
            {
                LoggerHelper.Error(response.Text);
                throw new Exception(response.Text);
            }
        }

        public void TokenLogout(string token)
        {
            if (string.IsNullOrEmpty(token)) return;

            LoggerHelper.Info("begin token logout, token = {0}", token);

            IXmlNode request = SSoCommandController.Instance.CreateRequest(token, SSoCommandCollection.TokenLogout, null);
            string xmlresponse = GetXmlResponse(url, request.Serialize());
        }


        public ISSoLoginResponse Login(string username, string md5password)
        {
            if (string.IsNullOrEmpty(username)) throw new Exception("missing username");
            if (string.IsNullOrEmpty(md5password)) throw new Exception("missing md5password");

            LoggerHelper.Info("begin login, username = {0}", username);

            SSoLoginRequest entityrequest = new SSoLoginRequest();
            entityrequest.UserName = username;
            entityrequest.Md5password = md5password;
            string content = XmlManager.Serialize(entityrequest).Serialize();
            string compresscontent = Pixysoft.IO.Compressor.Instance.Compress(content);
            string encryptcontent = Pixysoft.Security.DES.Encrypt(compresscontent, StringHelper.global_framework_id);
            string base64content = Pixysoft.Security.Base64.Encript(encryptcontent);
            IXmlNode request = SSoCommandController.Instance.CreateRequest(null, SSoCommandCollection.Login, base64content);
            IXmlNode response = GetResponse(url, request.Serialize());
            if (response == null)
                return null;
            base64content = response.Text;
            encryptcontent = Pixysoft.Security.Base64.Decript(base64content);
            compresscontent = Pixysoft.Security.DES.Decrypt(encryptcontent, StringHelper.global_framework_id);
            content = Pixysoft.IO.Compressor.Instance.DeCompress(compresscontent);
            try
            {
                SSoLoginResponse entityresponse = Pixysoft.IO.XmlImporter.Instance.XmlDeserialize<SSoLoginResponse>(content);
                return entityresponse;
            }
            catch (Exception ex)
            {
                throw new Exception(content);
            }
        }

        public bool IsPermitted(string username, string md5password, string resourcename)
        {
            if (string.IsNullOrEmpty(username)) throw new Exception("missing username");
            if (string.IsNullOrEmpty(md5password)) throw new Exception("missing md5password");
            if (string.IsNullOrEmpty(resourcename)) throw new Exception("missing resourcename");

            SSoIsPermittedRequest entityrequest = new SSoIsPermittedRequest();
            entityrequest.UserName = username;
            entityrequest.Md5password = md5password;
            entityrequest.ResourceName = resourcename;
            string content = XmlManager.Serialize(entityrequest).Serialize();
            string compresscontent = Pixysoft.IO.Compressor.Instance.Compress(content);
            string encryptcontent = Pixysoft.Security.DES.Encrypt(compresscontent, StringHelper.global_framework_id);
            string base64content = Pixysoft.Security.Base64.Encript(encryptcontent);
            IXmlNode request = SSoCommandController.Instance.CreateRequest(null, SSoCommandCollection.IsPermitted, base64content);
            IXmlNode response = GetResponse(url, request.Serialize());
            try
            {
                return bool.Parse(response.Text);
            }
            catch
            {
                LoggerHelper.Error(response.Serialize());

                throw new Exception(response.Serialize());
            }
        }


        private string GetXmlResponse(string url, string message)
        {
            LoggerHelper.Debug("CP.REQUEST:" + message);

            HttpResult result = new HttpPoster().Post(url, message);

            if (!result.IsSucceed)
                throw new Exception(result.ErrorMsg);

            if (!SSoCommandController.Instance.IsSucceed(result.Response))
                throw new Exception(result.Response);

            LoggerHelper.Debug("CP.RESPONSE:" + result.Response);

            return result.Response;
        }

        private IXmlNode GetResponse(string url, string message)
        {
            LoggerHelper.Debug("CP.REQUEST:" + message);

            HttpResult result = new HttpPoster().Post(url, message);

            if (!result.IsSucceed)
                throw new Exception(result.ErrorMsg);

            if (!SSoCommandController.Instance.IsSucceed(result.Response))
                throw new Exception(result.Response);

            LoggerHelper.Debug("CP.RESPONSE:" + result.Response);

            return XmlManager.Deserialize(result.Response);
        }

        private IXmlNode GetResponse(string url, string message, int timeout)
        {
            LoggerHelper.Debug("CP.REQUEST:" + message);

            HttpResult result = new HttpPoster(Encoding.UTF8, timeout).Post(url, message);

            if (!result.IsSucceed)
                throw new Exception(result.ErrorMsg);

            if (!SSoCommandController.Instance.IsSucceed(result.Response))
                throw new Exception(result.Response);

            LoggerHelper.Debug("CP.RESPONSE:" + result.Response);

            return XmlManager.Deserialize(result.Response);
        }
    }
}
